// Yue Marvin Tao
// 3/23/2022

package mult 

import chisel3._
import chisel3.util._

class MBFAInputBundle(val bits: Int) extends Bundle {
  val A = Input(UInt(bits.W))
  val B = Input(UInt(bits.W))
  val c = Input(UInt(1.W))
}

class MBFAOutputBundle(val bits: Int) extends Bundle {
  val S = Output(UInt(bits.W))
  val c = Output(UInt(1.W))
}

// Multi-Bit Full Adder (a.k.a. Ripple Carry Adder, RCA)

class MultiBitFullAdder(val bits: Int) extends Module {
  val in  = IO(new MBFAInputBundle(bits))
  val out = IO(new MBFAOutputBundle(bits))

  // Array of SBFAs
  val SBFAs = Array.fill(bits)(Module(new SingleBitFullAdder))

  // Do the wiring
  val carry = Wire(Vec(bits + 1, UInt(1.W)))
  val S = Wire(Vec(bits, Bool()))

  // wire in the carry-in to the LSB of carry array
  carry(0) := in.c

  for (i <- 0 until bits) {
    SBFAs(i).in.a := in.A(i)
    SBFAs(i).in.b := in.B(i)
    SBFAs(i).in.c := carry(i)
    carry(i+1) := SBFAs(i).out.c
    S(i) := SBFAs(i).out.s.asBool
  }

  // this turns n-bit bool array into a UInt
  out.S := S.asUInt
  out.c := carry(bits)
}
